package com.friend.service.user.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson2.JSON;
import com.api.RemoteJudgeService;
import com.api.domain.UserExeResult;
import com.api.domain.dto.JudgeSubmitDTO;
import com.api.domain.vo.UserQuestionResultVO;
import com.common.core.constants.Constants;
import com.common.core.domain.R;
import com.common.core.enums.ProgramType;
import com.common.core.enums.QuestionResType;
import com.common.core.enums.ResultCode;
import com.common.core.utils.ThreadLocalUtil;
import com.common.security.exception.ServiceException;
import com.friend.domain.exam.Exam;
import com.friend.domain.question.Question;
import com.friend.domain.question.QuestionCase;
import com.friend.domain.question.es.QuestionES;
import com.friend.domain.user.UserSubmit;
import com.friend.domain.user.dto.UserSubmitDTO;
import com.friend.integration.elasticsearch.QuestionRepository;
import com.friend.mapper.exam.ExamMapper;
import com.friend.mapper.question.QuestionMapper;
import com.friend.mapper.user.UserSubmitMapper;
import com.friend.integration.rabbit.JudgeProducer;
import com.friend.service.user.IUserQuestionService;
import com.friend.util.QuestionConverter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

@Service
@Slf4j
public class UserQuestionServiceImpl implements IUserQuestionService {


    @Autowired
//    @Qualifier("FriendQuestionRepository")
    private QuestionRepository questionRepository;

    @Autowired
    private QuestionMapper questionMapper;

    @Autowired
    private UserSubmitMapper userSubmitMapper;

    @Autowired
    private RemoteJudgeService remoteJudgeService;

    @Autowired
    private JudgeProducer judgeProducer;

    @Autowired
    private ExamMapper examMapper;

    @Override
    public R<UserQuestionResultVO> submit(UserSubmitDTO submitDTO) {
        Integer programType = submitDTO.getProgramType();
        if (ProgramType.JAVA.getValue().equals(programType)) {
            //按照java逻辑处理
            JudgeSubmitDTO judgeSubmitDTO = assembleJudgeSubmitDTO(submitDTO);
            return remoteJudgeService.doJudgeJavaCode(judgeSubmitDTO);
        }
        throw new ServiceException(ResultCode.FAILED_NOT_SUPPORT_PROGRAM);
    }

    @Override
    public boolean rabbitSubmit(UserSubmitDTO submitDTO) {
        // 验证竞赛状态（如果是竞赛提交）
        if (submitDTO.getExamId() != null) {
            validateExamStatus(submitDTO.getExamId());
        }
        
        Integer programType = submitDTO.getProgramType();
        if (ProgramType.JAVA.getValue().equals(programType)) {
            //按照java逻辑处理
            JudgeSubmitDTO judgeSubmitDTO = assembleJudgeSubmitDTO(submitDTO);
            judgeProducer.produceMsg(judgeSubmitDTO);
            return true;
        }
        throw new ServiceException(ResultCode.FAILED_NOT_SUPPORT_PROGRAM);
    }

    @Override
    public UserQuestionResultVO exeResult(Long examId, Long questionId, String currentTime) {
        Long userId = ThreadLocalUtil.get(Constants.USER_ID, Long.class);
        UserSubmit userSubmit = userSubmitMapper.selectCurrentUserSubmit(userId, examId, questionId, currentTime);
        UserQuestionResultVO resultVO = new UserQuestionResultVO();
        if (userSubmit == null) {
            resultVO.setPass(QuestionResType.IN_JUDGE.getValue());
        } else {
            resultVO.setPass(userSubmit.getPass());
            resultVO.setExeMessage(userSubmit.getExeMessage());
            if (StrUtil.isNotEmpty(userSubmit.getCaseJudgeRes())) {
                resultVO.setUserExeResultList(JSON.parseArray(userSubmit.getCaseJudgeRes(), UserExeResult.class));
            }
        }
        return resultVO;
    }

    /**
     * 验证竞赛状态
     */
    private void validateExamStatus(Long examId) {
        Exam exam = examMapper.selectById(examId);
        if (exam == null) {
            throw new ServiceException(ResultCode.EXAM_NOT_EXISTS);
        }
        
        // 检查竞赛是否已发布
        if (!Constants.TRUE.equals(exam.getStatus())) {
            throw new ServiceException(ResultCode.EXAM_NOT_EXISTS);
        }
        
        // 检查竞赛是否已开始
        if (exam.getStartTime().isAfter(LocalDateTime.now())) {
            throw new ServiceException(ResultCode.EXAM_START_TIME_BEFORE_CURRENT_TIME);
        }
        
        // 检查竞赛是否已结束
        if (exam.getEndTime().isBefore(LocalDateTime.now())) {
            throw new ServiceException(ResultCode.EXAM_IS_FINISH);
        }
    }

    private JudgeSubmitDTO assembleJudgeSubmitDTO(UserSubmitDTO submitDTO) {
        Long questionId = submitDTO.getQuestionId();
        
        QuestionES questionES = questionRepository.findById(questionId).orElse(null);
        JudgeSubmitDTO judgeSubmitDTO = new JudgeSubmitDTO();
        
        if (questionES != null) {
            BeanUtil.copyProperties(questionES, judgeSubmitDTO);
            // 修复时间限制单位不一致问题：数据库中是秒，JudgeSubmitDTO需要毫秒
            if (questionES.getTimeLimit() != null) {
                judgeSubmitDTO.setTimeLimit(questionES.getTimeLimit() * 1000); // 秒转毫秒
            }
            // 修复内存限制单位问题：数据库中是KB，保持不变（已经是KB单位）
            // spaceLimit 保持原值，因为数据库和接口都是KB单位
        } else {
            Question question = questionMapper.selectById(questionId);
            if (question == null) {
                throw new ServiceException(ResultCode.FAILED_NOT_EXISTS);
            }
            BeanUtil.copyProperties(question, judgeSubmitDTO);
            // 修复时间限制单位不一致问题：数据库中是秒，JudgeSubmitDTO需要毫秒
            if (question.getTimeLimit() != null) {
                judgeSubmitDTO.setTimeLimit(question.getTimeLimit() * 1000); // 秒转毫秒
            }
            questionES = QuestionConverter.toQuestionES(question);
            questionRepository.save(questionES);
        }
        
        // 验证必要字段
        if (questionES.getQuestionCase() == null || questionES.getQuestionCase().isEmpty()) {
            log.error("题目用例数据为空，题目ID: {}", questionId);
            throw new ServiceException(ResultCode.FAILED_PARAM_ERROR);
        }
        if (questionES.getMainFuc() == null || questionES.getMainFuc().isEmpty()) {
            log.error("题目主函数为空，题目ID: {}", questionId);
            throw new ServiceException(ResultCode.FAILED_PARAM_ERROR);
        }
        
        
        judgeSubmitDTO.setUserId(ThreadLocalUtil.get(Constants.USER_ID, Long.class));
        judgeSubmitDTO.setExamId(submitDTO.getExamId());
        judgeSubmitDTO.setProgramType(submitDTO.getProgramType());
        String connectedCode = codeConnect(submitDTO.getUserCode(), questionES.getMainFuc());
        judgeSubmitDTO.setUserCode(connectedCode);
        
        List<QuestionCase> questionCaseList;
        try {
            // 尝试直接解析原始数据
            questionCaseList = JSONUtil.toList(questionES.getQuestionCase(), QuestionCase.class);
            if (questionCaseList == null || questionCaseList.isEmpty()) {
                questionCaseList = createDefaultQuestionCase();
            }
        } catch (Exception e) {
            questionCaseList = createDefaultQuestionCase();
        }
        
        List<String> inputList = questionCaseList.stream().map(QuestionCase::getInput).toList();
        List<String> outputList = questionCaseList.stream().map(QuestionCase::getOutput).toList();
        judgeSubmitDTO.setInputList(inputList);
        judgeSubmitDTO.setOutputList(outputList);
        
        return judgeSubmitDTO;
    }

    private String codeConnect(String userCode, String mainFunc) {
        
        if (userCode == null || userCode.trim().isEmpty()) {
            log.error("用户代码为空");
            throw new ServiceException(ResultCode.FAILED_PARAM_ERROR);
        }
        if (mainFunc == null || mainFunc.trim().isEmpty()) {
            log.error("mainFunc为空");
            throw new ServiceException(ResultCode.FAILED_PARAM_ERROR);
        }
        
        // 检查用户代码是否已经包含main方法
        if (userCode.contains("public static void main")) {
            return userCode;
        }
        
        // 使用数据库中的mainFunc，但进行必要的修复
        String fixedMainFunc = fixMainFunction(mainFunc);
        
        // 检查 mainFunc 中是否包含辅助类定义（如 ListNode、TreeNode 等）
        String helperClasses = "";
        String actualMainFunc = fixedMainFunc;
        
        if (fixedMainFunc.contains("class ")) {
            // 提取所有类定义（包括 ListNode、TreeNode 等）
            int mainMethodIndex = fixedMainFunc.indexOf("public static void main");
            if (mainMethodIndex > 0) {
                // 类定义在 main 方法之前
                helperClasses = fixedMainFunc.substring(0, mainMethodIndex).trim();
                actualMainFunc = fixedMainFunc.substring(mainMethodIndex).trim();
            }
        }
        
        // 生成完整的Java代码
        StringBuilder result = new StringBuilder();
        
        // 1. 添加必要的import语句
        result.append("import java.util.*;\n");
        result.append("import java.util.Map;\n");
        result.append("import java.util.HashMap;\n");
        result.append("import java.util.Scanner;\n\n");
        
        // 2. 添加辅助类定义（如 ListNode）- 在 Solution 类之前
        if (!helperClasses.isEmpty()) {
            result.append(helperClasses).append("\n\n");
        }
        
        // 3. 添加用户代码（Solution 类）
        result.append(userCode);
        
        // 4. 在 Solution 类的最后一个}之前插入 main 方法
        String targetCharacter = "}";
        int targetLastIndex = result.lastIndexOf(targetCharacter);
            
        if (targetLastIndex != -1) {
            // 在最后一个}之前插入main函数
            result.insert(targetLastIndex, "\n" + actualMainFunc + "\n");
        } else {
            // 如果没有找到}，直接在末尾添加main函数
            result.append("\n").append(actualMainFunc);
        }
        
        String finalCode = result.toString();
        
        return finalCode;
    }
    
    /**
     * 修复数据库中的mainFunc，确保使用命令行参数而不是Scanner
     */
    private String fixMainFunction(String mainFunc) {
        if (mainFunc == null || mainFunc.trim().isEmpty()) {
            log.warn("数据库中的mainFunc为空，使用默认main函数");
            return generateDefaultMainFunction();
        }
        
        // 修复Scanner(System.in)为命令行参数
        String fixedMainFunc = mainFunc;
        
        // 检查是否包含Scanner(System.in)
        if (fixedMainFunc.contains("Scanner(System.in)")) {
            
            // 替换Scanner相关代码
            fixedMainFunc = fixedMainFunc.replace("Scanner scanner = new Scanner(System.in);", "");
            fixedMainFunc = fixedMainFunc.replace("scanner.hasNext()", "args.length >= 2");
            fixedMainFunc = fixedMainFunc.replace("scanner.nextLine()", "args[0] + \" \" + args[1]");
            fixedMainFunc = fixedMainFunc.replace("scanner.close();", "");
            
            // 添加命令行参数检查
            if (!fixedMainFunc.contains("args.length >= 2")) {
                fixedMainFunc = fixedMainFunc.replace("if (", "if (args.length >= 2 && ");
            }
        }
        
        // 确保main函数签名正确
        if (!fixedMainFunc.contains("public static void main(String[] args)")) {
            log.warn("main函数签名不正确，进行修复");
            fixedMainFunc = fixedMainFunc.replace("public static void main", "public static void main(String[] args)");
        }
        
        return fixedMainFunc;
    }
    
    /**
     * 生成默认的main函数（当数据库中的mainFunc不可用时）
     */
    private String generateDefaultMainFunction() {
        return """
    public static void main(String[] args) {
        // 从命令行参数读取输入
        if (args.length >= 2) {
            String arrayStr = args[0];
            int target = Integer.parseInt(args[1]);
            
            // 解析数组
            arrayStr = arrayStr.substring(1, arrayStr.length() - 1); // 去掉方括号
            String[] numStrs = arrayStr.split(",");
            int[] nums = new int[numStrs.length];
            for (int i = 0; i < numStrs.length; i++) {
                nums[i] = Integer.parseInt(numStrs[i].trim());
            }
            
            // 调用用户的方法
            Solution solution = new Solution();
            int[] result = solution.twoSum(nums, target);
            
            // 输出结果
            System.out.print("[");
            for (int i = 0; i < result.length; i++) {
                System.out.print(result[i]);
                if (i < result.length - 1) {
                    System.out.print(",");
                }
            }
            System.out.println("]");
        }
    }
""";
    }
    
    


    /**
     * 创建默认题目用例，用于数据异常时的兜底处理
     */
    private List<QuestionCase> createDefaultQuestionCase() {
        List<QuestionCase> defaultCases = new ArrayList<>();
        QuestionCase defaultCase = new QuestionCase();
        defaultCase.setInput("[]");
        defaultCase.setOutput("\"\"");
        defaultCases.add(defaultCase);
        return defaultCases;
    }


}